package com.soft.mainsite.component.beetl.html;

import com.soft.mainsite.common.constant.CmsConst;
import com.soft.mainsite.common.exception.SystemException;
import com.soft.mainsite.common.utils.StrUtil;
import com.soft.mainsite.component.beetl.thread.HtmlThread;
import com.soft.mainsite.module.staticstrategy.exception.HtmlStaticException;
import com.soft.mainsite.module.web.cms.service.SiteService;
import com.soft.mainsite.mybatis.model.TCmsSite;
import lombok.extern.slf4j.Slf4j;
import org.beetl.core.GroupTemplate;
import org.beetl.core.Template;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import javax.servlet.http.HttpServletRequest;
import java.io.File;
import java.io.StringWriter;
import java.util.Map;


/**
 * 页面静态化工具类
 *
 * @author liupengtao
 * @date 2019/04/29
 */
@Component
@Slf4j
public class BeetlHtmlUtil {

    @Autowired
    private GroupTemplate groupTemplate;

    @Autowired
    private SiteService siteService;

    @Value("${system.http.protocol}")
    private String httpProtocol;

    @Value("${system.http.host}")
    private String httpHost;

    @Value("${system.site.subfix}")
    private String siteSubfix;

    @Value("${system.site.prefix}")
    private String sitePrefix;

    @Value("${system.site.static.path}")
    String staticPath;

    @Value("${system.site.static.site.path}")
    String sitePath;

    @Value("${system.site.static.common.path}")
    String commonPath;

    @Value("${system.site.static.resourcesPath.path}")
    String resourcesPath;


    private static final String WWW = "www";
    private static final String TEMPLATES = "templates";

    /**
     * 静态化页面公用方法
     *
     * @param request  request
     * @param siteId   站点id
     * @param action   请求路径
     * @param siteInfo 站点信息
     * @param tplPath  模板路径
     * @param tplName  模板名称
     * @param isPub    是否公共
     * @throws HtmlStaticException
     */
    public void create(HttpServletRequest request, Integer siteId, String action, Map<String, Object> siteInfo, String tplPath, String tplName, boolean isPub,String tplType) throws Exception {

        try {
            //构建模板存储路径
            String view = new StringBuilder(WWW)
                    .append(File.separator)
                    .append(tplPath)
                    .append(File.separator)
                    .append(tplName)
                    .append(siteSubfix)
                    .toString();

            view = filterPath(view);

            TCmsSite siteMain = siteService.findVoById(CmsConst.MAIN_SITE_ID);
            TCmsSite site = siteService.findVoById(siteId);

            // 用于判断模板文件是否存在，不存在会抛异常
            File fileResource = new File(staticPath + File.separator + TEMPLATES + File.separator +view);
            if (!fileResource.exists()){
                log.error("不存在的模板文件为：{}", fileResource);
                throw new SystemException("模板文件不存在，请检查！");
            }

            Template template = groupTemplate.getTemplate(view);
            StringWriter writer = new StringWriter();

            // 构建模板基础数据
            builderTemplate(template, request, null);

            template.binding(siteInfo);
            template.binding("siteType", site.getSiteType());
            template.binding("commonPath","commonHtml/content/"+site.getSiteKey());
            template.binding("deviceType",CmsConst.getStaticTypeByTplType(tplType));

            template.renderTo(writer);

            HtmlObject obj = new HtmlObject();
            // 替换静态化url路径
            String content;
            if (CmsConst.WEB_PATH.equals(tplPath)){
                content = format(writer.toString(), site.getSiteKey(), siteMain.getSiteKey(), CmsConst.WEB_PATH);
            }else {
                content = format(writer.toString(), site.getSiteKey(), siteMain.getSiteKey(), CmsConst.MOBILE_PATH);
            }
            obj.setContent(content);

            //获取静态化存储路径
            String fileUrl = getUrl(site, action, tplPath, isPub);

            //如果是转发页获取转发页存储路径
            if (CmsConst.FORWARD.equals(tplName)) {
                fileUrl = getForwordUrl(site, action);
            }

            obj.setFileUrl(fileUrl);
            HtmlThread.addHtml(obj);

        } catch (Exception e) {
            log.error("页面静态化失败", e);
            siteService.updateStaticStatus(siteId, false);
            throw e;
        }

    }


    /**
     * 静态化公共列表方法
     *
     * @param request    request
     * @param action     请求路径
     * @param siteType   站点类型
     * @param tplPath    模板路径
     * @param renderName 静态化名称
     * @throws HtmlStaticException
     */
    public void createCommonList(HttpServletRequest request, Long categoryId, String action, String siteType, String tplPath, String renderName,String type) throws HtmlStaticException {

        try {
            //构建模板路径
            String view = new StringBuilder(WWW)
                    .append(File.separator)
                    .append(tplPath)
                    .append(File.separator)
                    .append(renderName)
                    .append(siteSubfix)
                    .toString();

            view = filterPath(view);

            TCmsSite site = siteService.findVoById(CmsConst.MAIN_SITE_ID);

            /*ClassPathResource classPathResource = new ClassPathResource(TEMPLATES + File.separator + view);
            //用于判断模板文件是否存在，不存在会抛异常
            classPathResource.getFile();*/

            File fileResource = new File(staticPath + File.separator + TEMPLATES + File.separator +view);
            //用于判断模板文件是否存在，不存在会抛异常
            if (!fileResource.exists()){
                log.error("不存在的模板文件为：{}", fileResource);
                throw new SystemException("模板文件不存在，请检查！");
            }

            Template template = groupTemplate.getTemplate(view);
            StringWriter writer = new StringWriter();

            // 构建模板基础数据
            builderTemplate(template, request, null);

            template.binding("isPub", CmsConst.IS_PUB);
            template.binding("siteId", CmsConst.MAIN_SITE_ID);
            template.binding("siteType", siteType);
            template.binding("categoryId", categoryId);
            template.binding("siteKey", site.getSiteKey());
            template.binding("deviceType",CmsConst.getStaticTypeByTplType(type));
            template.renderTo(writer);

            HtmlObject obj = new HtmlObject();

            // 替换公共列表静态化url路径
            String content;
            if (CmsConst.WEB_PATH.equals(tplPath)){
                content = formatCommon(writer.toString(), site.getSiteKey(), CmsConst.WEB_PATH);
            }else {
                content = formatCommon(writer.toString(), site.getSiteKey(), CmsConst.MOBILE_PATH);
            }
            obj.setContent(content);

            String fileUrl = getPubListUrl(action, tplPath, siteType);

            obj.setFileUrl(fileUrl);
            HtmlThread.addHtml(obj);

        } catch (Exception e) {
            log.error("公共栏目静态化失败", e);
        }
    }

    /**
     * 替换静态化url路径
     *
     * @param page        页面
     * @param siteKey     站点别名
     * @param mainSiteKey 主站点别名
     * @return
     */
    private String format(String page, String siteKey, String mainSiteKey, String staticType) {
        String view = page.replace("/" + siteKey + "/", "/"+ staticType + "/")
                .replace("/" + mainSiteKey + "/", "/"+ staticType + "/")
                .replace("\"" + httpProtocol + "://" + httpHost + "/static", "\"" + resourcesPath)
                .replace("\"" + httpProtocol + "://" + httpHost + siteKey + "/\"", "\"" + httpProtocol + "://" + httpHost + siteKey + "/index.html\"");
        return view;
    }

    /**
     * 替换公共列表静态化url路径
     *
     * @param page 页面
     * @param siteKey 站点别名
     * @return
     */
    private String formatCommon(String page, String siteKey, String staticType) {
        String view = page.replace("/" + siteKey + "/", "/" + staticType + "/")
                .replace("\"" + httpProtocol + "://" + httpHost + "/static", "\"" + resourcesPath)
                .replace("/res", resourcesPath)
                .replace("\"" + httpProtocol + "://" + httpHost + "/" + sitePrefix + "/\"", "\"" + httpProtocol + "://" + httpHost + siteKey + "/index.html\"");
        return view;
    }

    /**
     * 静态化存储路径url
     *
     * @param site 站点
     * @param action 动作
     * @param tplType 模板类型
     * @return
     */
    private String getUrl(TCmsSite site, String action, String tplType, boolean isPub) {
        if (StrUtil.isBlank(action)) {
            action = "default";
        }
        StringBuilder url = new StringBuilder();
        if (isPub) {
            url.append(staticPath)
                    .append(File.separator)
                    .append(commonPath)
                    .append(File.separator)
                    .append("content")
                    .append(File.separator)
                    .append(tplType)
                    .append(File.separator)
                    .append(action)
                    .append(siteSubfix);
        } else {
            url.append(staticPath)
                    .append(File.separator)
                    .append(sitePath)
                    .append(File.separator)
                    .append(site.getSiteKey())
                    .append(File.separator)
                    .append(tplType)
                    .append(File.separator)
                    .append(action)
                    .append(siteSubfix);
        }

        return url.toString();
    }

    /**
     * 获取转发页静态化生成路径
     *
     * @param site 站点
     * @param action 动作
     * @return
     */
    private String getForwordUrl(TCmsSite site, String action) {
        StringBuilder url = new StringBuilder();
        url.append(staticPath)
                .append(File.separator)
                .append(sitePath)
                .append(File.separator)
                .append(site.getSiteKey())
                .append(File.separator)
                .append("index.html");
        return url.toString();
    }


    /**
     * 获取公共列表静态化存储路径
     *
     * @param action 动作
     * @param tplType 模板类型
     * @return
     */
    private String getPubListUrl(String action, String tplType, String siteType) {
        if (StrUtil.isBlank(action)) {
            action = "default";
        }

        action = action.replace("common/", "");

        StringBuilder url = new StringBuilder();
        if (StrUtil.isBlank(siteType)) {
            url.append(staticPath)
                    .append(File.separator)
                    .append(commonPath)
                    .append(File.separator)
                    .append(tplType)
                    .append(File.separator)
                    .append(action)
                    .append(siteSubfix);
        } else {
            url.append(staticPath)
                    .append(File.separator)
                    .append(commonPath)
                    .append(File.separator)
                    .append(tplType)
                    .append(File.separator)
                    .append(siteType)
                    .append(File.separator)
                    .append(action)
                    .append(siteSubfix);
        }

        return url.toString();
    }


    /**
     * 构建模板基础数据
     *
     * @param template 模板
     * @param request request请求
     * @param categoryId 栏目id
     */
    private void builderTemplate(Template template, HttpServletRequest request, Long categoryId) {

        template.binding("request", request);
        template.binding("ctxPath", request.getContextPath());
        template.binding("baseURL", httpProtocol + "://" + httpHost);
        template.binding("isStatic", true);

        if (categoryId != null) {
            template.binding("categoryId", categoryId);
        }
    }

    private String filterPath(String path) {
        return path.replaceAll("\\\\", "/");
    }

}
